/*
 *  Filename:      meos_pwr_mgr.c
 *  Author:         Erick Huang<erickhuang1989@gmail.com>
 *  Revised:        2014-12-16
 *  Description:   This file contains the Power Management API.
 *
 *  Copyright (c) Erick Huang. All rights reserved.
 */
#include "meos_api.h"
#include "hal_drivers.h"
#include "hal_sleep.h"

typedef struct
{
  	uint16 pwrmgr_task_state;   // bit maps and support 16 tasks.
  	uint8  pwrmgr_device;
} pwrmgr_attribute_t;

static pwrmgr_attribute_t pwrmgr_attr;


void meos_pwrmgr_init( void )
{
  	pwrmgr_attr.pwrmgr_device = PWRMGR_ALWAYS_ON;    // Default to no power conservation.
  	pwrmgr_attr.pwrmgr_task_state = 0;               // Cleared.  All set to conserve
}

/*********************************************************************
 * @fn      meos_pwrmgr_device
 *
 * @brief   Set the device power characteristic.
 *
 * @param   pwrmgr_device - type of power devices. With PWRMGR_ALWAYS_ON
 *          selection, there is no power savings and the device is most
 *          likely on mains power. The PWRMGR_BATTERY selection allows the
 *          HAL sleep manager to enter sleep.
 *
 * @return  none
 */
void meos_pwrmgr_device( uint8 pwrmgr_device )
{
  	pwrmgr_attr.pwrmgr_device = pwrmgr_device;
}


/*********************************************************************
 * @fn      meos_pwrmgr_task_state
 *
 * @brief   This function is called by each task to state whether or
 *          not this task wants to conserve power.The task will call this function to
 *         vote whether it wants the OSAL to conserve power or it wants to
 *         hold off on the power savings. By default, when a task is created,
 *         its own power state is set to conserve. If the task always wants
 *         to converse power, it doesn't need to call this function at all.
 *        It is important for the task that changed the power manager task
 *        state to PWRMGR_HOLD to switch back to PWRMGR_CONSERVE when the
 *        hold period ends.
 *
 * @param   task_id - calling task ID.
 *          state - whether the calling task wants to
 *          conserve power or not.
 *
 * @return  SUCCESS if task complete
 */
Status_t meos_pwrmgr_task_state( uint8 task_id, uint8 state )
{
  	if ( task_id >= tasksCnt )
    	return INVALID_TASK;

  	if ( state == PWRMGR_CONSERVE )
  	{
    	// Clear the task state flag
    	pwrmgr_attr.pwrmgr_task_state &= ~(1 << task_id );
  	}
  	else
  	{
    	// Set the task state flag
    	pwrmgr_attr.pwrmgr_task_state |= (1 << task_id);
  	}

  	return SUCCESS;
}

/*********************************************************************
 * @fn      meos_pwrmgr_standby
 *
 * @brief   This function is called from the main MEOS loop when there are
 *          no events scheduled and shouldn't be called from anywhere else.
 *
 * @param   none.
 *
 * @return  none.
 */
void meos_pwrmgr_standby( void )
{
  	uint32        next;
  	halIntState_t intState;

  	// Should we even look into power conservation
  	if ( pwrmgr_attr.pwrmgr_device != PWRMGR_ALWAYS_ON )
  	{
    	// Are all tasks in agreement to conserve
    	if ( pwrmgr_attr.pwrmgr_task_state == 0 )
    	{
      		// Get next time-out
      		next = meos_next_timeout();

      		// Put the processor into sleep mode
      		hal_sleep( next );
    	}
  	}
}

